package folder.main.exp0.controllers;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;

import org.apache.commons.math3.stat.descriptive.SummaryStatistics;

import folder.model.link.Link;
import folder.model.node.Node;

public abstract class ControllerFinding
{	
	protected LinkedHashMap< Node, Node > matches;
	public List< Node > controllers;
	
	protected void setMatches( LinkedHashMap< Node, Node > matches )
	{
		this.matches = matches;
		this.controllers = this.computeControllers( matches );
	}
	
	
	
	
	protected List< Node > computeControllers( LinkedHashMap< Node, Node > matches )
	{
		List< Node > controllers = new ArrayList< Node >();
		Iterator< Entry< Node, Node > > iterator = matches.entrySet().iterator();
				
		while( iterator.hasNext() )
		{
			Node controller = iterator.next().getValue();
			
			if( !controllers.contains( controller ) )
				controllers.add( controller );
		}
		
		return controllers;
	}
	
	public double getMeanABW()
	{
		SummaryStatistics summaryStatistics = new SummaryStatistics();
		
		for( Node controller: controllers )
			summaryStatistics.addValue( getABW( controller ) );
		
		return summaryStatistics.getMean();
	}
	
	public double getMeanDelay( double delays[][] )
	{
		SummaryStatistics summaryStatistics1 = new SummaryStatistics();
		
		for( Node controller: this.controllers )
		{	
			SummaryStatistics summaryStatistics2 = new SummaryStatistics();
			Iterator< Entry< Node, Node > > iterator = this.matches.entrySet().iterator();
			
			while( iterator.hasNext() )
			{
				Entry< Node, Node > pair = iterator.next();
				
				if( pair.getValue().equals( controller ) )
					if( delays[ pair.getKey().getIdentifier() ][ controller.getIdentifier() ] > 0 )
						summaryStatistics2.addValue( delays[ pair.getKey().getIdentifier() ][ controller.getIdentifier() ] );
			}
			
			summaryStatistics1.addValue( summaryStatistics2.getMean() );
		}
		
		return summaryStatistics1.getMean();
	}
	
	public double[] ABWsTable( List< Node > nodes, boolean toPrint )
	{
		double ABW[] = new double[ nodes.size() ];
		
		for( Node node: nodes )
			ABW[ node.getIdentifier() ] = getABW( node );
		
		if( toPrint )
			for( Node node: nodes )
				System.out.println( "ABW[" + node.getIdentifier() + "]: " + ABW[ node.getIdentifier() ] );
		
		return ABW;
	}
	
	public double getABW( Node node )
	{
		double sum = 0;
		
		for( Link link: node.getLinks() )
			sum += link.getBandwidthAvailable();
		
		return node.getLinks().size() * sum;
	}
	
}
